/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = ora_ttc7_logon.c                                   */
/*  NOTE      =                                                    */
/*  DATE      = 2014/10/15 by songbb                               */
/*******************************************************************/

#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>

#include "frstr.h"
#include "frmem.h"
#include "frcomm.h"
#include "frlog.h"

#include "conntrack.h"
#include "frct_comm.h"

#include "../../ora_core.h"
#include "../../comm/ora_comm.h"
#include "../../comm/ora_util.h"
#include "../ora_mar_engine.h"
#include "ora_ttc7_tti_oer.h"
#include "ora_ttc7_logon.h"

/*******************************************************************************
*  FUNC     :  解析0x0352和0x0351的logon请求包
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_ttc7_logon_unpack_req(Conntrack *p_st_conn
                            , L7session_ora *p_st_sess
                            , L7_ora_packet *p_st_ora_packet)
{
    char c_tmp = 0;
    short s_tmp = 0;
    int i_tmp = 0;
    long long ll_tmp = 0;
    char *p_tmp = NULL;
    int i_user_len = 0;
    int i_password_len = 0;
    int i_terminal_len = 0;
    int i_machine_len = 0;
    int i_sysusername_len = 0;
    int i_processid_len = 0;
    int i_programname_len = 0;

    if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_tmp) != FR_SUCC) // seqNumber
        goto error;

    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) == FR_FAIL)          // user 标志位
        goto error;

    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_user_len) == FR_FAIL)     // user length
        goto error;

    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) == FR_FAIL)          // password 标志位
        goto error;

    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_password_len) == FR_FAIL) // password length
        goto error;

    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_tmp) == FR_FAIL)          // auditFlag
        goto error;

    if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_tmp) == FR_FAIL)         // connectFlag
        goto error;

    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_tmp) == FR_FAIL)          // revisionLev
        goto error;

    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) == FR_FAIL)          // padO2U
        goto error;

    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) == FR_FAIL)          // terminal 标志位
        goto error;

    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_terminal_len) == FR_FAIL) // terminal length
        goto error;

    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) == FR_FAIL)          // machine 标志位
        goto error;

    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_machine_len) == FR_FAIL)  // machine length
        goto error;

    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) == FR_FAIL)          // sysUserName 标志位
        goto error;

    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_sysusername_len) == FR_FAIL)  // sysUserName length
        goto error;

    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_tmp) == FR_FAIL)              // sizeofUCAUAC
        goto error;

    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) == FR_FAIL)              // processID 标志位
        goto error;

    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_processid_len) == FR_FAIL)    // processID length
        goto error;

    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) == FR_FAIL)              // programName 标志位
        goto error;

    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_programname_len) == FR_FAIL)  // programName length
        goto error;

    if (ora_mar_unmarshalSB2(p_st_sess, p_st_ora_packet, &s_tmp) == FR_FAIL)              // svrAttrPtr
        goto error;

    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_tmp) == FR_FAIL)              // lenSvrAttrs
        goto error;

    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) == FR_FAIL)              // svrDataO2U
        goto error;

    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_tmp) == FR_FAIL)              // lenSvrData
        goto error;

    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) == FR_FAIL)              // svrInfoO2U
        goto error;

    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, &i_tmp) == FR_FAIL)              // svrInfoLen
        goto error;

    if (ora_mar_unmarshalO2U(p_st_sess, p_st_ora_packet, &c_tmp) == FR_FAIL)              // retLenO2U
        goto error;

    if (ora_mar_unmarshalCHR(i_user_len, p_st_sess, p_st_ora_packet, &p_tmp, &i_tmp) == FR_SUCC)  // user
    {
        ora_free((void **) &(p_st_sess->p_username));
        if ((p_st_sess->p_username = (char *) ora_malloc((i_tmp + 1) * sizeof(char), bytebuff_remaining(p_st_ora_packet->p_st_packet) + 1)) == NULL)
        {
            ORA_MALLOCK_ERR;
            ora_free((void **) &p_tmp);
            goto error;
        }
        memcpy(p_st_sess->p_username, p_tmp, (size_t) i_tmp);
        p_st_sess->p_username[i_tmp] = '\0';
        ORA_PRINT_DBG("username:[%s]\n", p_st_sess->p_username);
        ora_free((void **) &p_tmp);
    }
    else
        goto error;

    if (i_password_len > 0)
    {
        if (ora_mar_skipCHR(i_password_len, p_st_sess, p_st_ora_packet) != FR_SUCC) // password
            goto error;
    }

    if (ora_mar_skipCHR(i_terminal_len, p_st_sess, p_st_ora_packet) != FR_SUCC) // terminal
        goto error;

    if (ora_mar_skipCHR(i_machine_len, p_st_sess, p_st_ora_packet) != FR_SUCC) // machine
        goto error;

    if (ora_mar_skipCHR(i_sysusername_len, p_st_sess, p_st_ora_packet) != FR_SUCC) // sysUserName
        goto error;

    if (i_processid_len > 0)
    {
        if (ora_mar_skipCHR(i_processid_len, p_st_sess, p_st_ora_packet) != FR_SUCC) // processID
            goto error;
    }

    if (ora_mar_skipCHR(i_programname_len, p_st_sess, p_st_ora_packet) != FR_SUCC) // programName
        goto error;

    ORA_PRINT_SESS(p_st_sess);

    return FR_SUCC;
error:
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  解析0x0352请求的响应包
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_ttc7_logon1_unpack_resp(Conntrack *p_st_conn
                                , L7session_ora *p_st_sess
                                , L7_ora_packet *p_st_ora_packet)
{
    int i_tmp = 0;
    short s_ret_code;                                // return code
    int i_flag = 0;

    while(1)
    {
        if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_ret_code) == FR_FAIL)
            goto error;

        switch (s_ret_code)
        {
            case 8:
                if (i_flag != 0)
                    goto error;

                if (ora_mar_unmarshalUB2(p_st_sess, p_st_ora_packet, &i_tmp) == FR_FAIL)              // 跳过
                    goto error;

                if (ora_mar_skipCHR(APM_ORA_ENCRYPTEDSK_LEN, p_st_sess, p_st_ora_packet) != FR_SUCC)          // encryptedSK
                    goto error;

                i_flag = 1;
                break;

            case 4:
                if (ora_ttc7_tti_oer_unmarshal(p_st_conn, p_st_sess, p_st_ora_packet, APM_ORA_SESS_IS_LOGON, NULL) == FR_FAIL)
                    goto error;
                goto success; // 直接退出循环

            default:
                goto error;
        }
    }

success:
    return FR_SUCC;
error:
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  解析0x0351请求的响应包
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_ttc7_logon2_unpack_resp(Conntrack *p_st_conn
                                , L7session_ora *p_st_sess
                                , L7_ora_packet *p_st_ora_packet)
{
    short s_ret_code;                                // return code

    while(1)
    {
        if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_ret_code) == FR_FAIL)
            goto error;

        switch (s_ret_code)
        {
            case 8:
                goto error;
            case 4:
                if (ora_ttc7_tti_oer_unmarshal(p_st_conn, p_st_sess, p_st_ora_packet, APM_ORA_SESS_IS_LOGON, NULL) == FR_FAIL)
                    goto error;
                goto success; // 直接退出循环
            case 15:
                if (ora_ttc7_tti_oer_unmarshal_warn(p_st_conn, p_st_sess, p_st_ora_packet) == FR_FAIL)
                    goto error;
                goto success; // XXX 直接退出循环，此处有待斟酌
            default:
                goto error;
        }
    }

success:
    return FR_SUCC;
error:
    return FR_FAIL;
}
